﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using T.FAS.Runtime.Base.Entity;
using T.FAS.Runtime.Metadata.Entity;
using T.FAS.Runtime.Metadata.SPI;
using T.ServiceComponent.Error;

namespace T.FAS.Runtime.Metadata.Dao
{
    /// <summary>
    /// 元数据管理接口创建者工厂
    /// </summary>
    public class MetaDataFactory
    {
        public static IMetaDataCompiler CreateMetaDataCompiler(string metadataType)
        {
            try
            {
                var config = GetMetaDataConfiguration(metadataType);

                if (string.IsNullOrWhiteSpace(config.MetaDataCompiler))
                {
                    throw new FasException(MetaDataExceptionCode.GetMetaDataInfoException,
                        string.Format(MetaDataExceptionCode.GetMetaDataInfoExceptionMessage, metadataType + ": MetaDataCompiler为空"));
                }

                return CreateInstance<IMetaDataCompiler>(config.MetaDataCompiler);
            }
            catch (Exception e)
            {
                throw new FasException(MetaDataExceptionCode.GetMetaDataMgrException,
                    string.Format(MetaDataExceptionCode.GetMetaDataMgrExceptionMessage, metadataType), e);
            }
        }
        public static IExtMetaDataManager CreateExtMetaDataManager(string metadataType)
        {
            try
            {
                var config = GetMetaDataConfiguration(metadataType);

                if (string.IsNullOrWhiteSpace(config.MetaDataExtManagerType))
                {
                    return null;
                }

                return CreateInstance<IExtMetaDataManager>(config.MetaDataExtManagerType);
            }
            catch (Exception e)
            {
                throw new FasException(MetaDataExceptionCode.GetMetaDataExtManagerException,
                    string.Format(MetaDataExceptionCode.GetMetaDataExtManagerExceptionMessage, metadataType), e);
            }
        }

        public static IMetaDataManager CreateMetaDataManager(string metadataType)
        {
            try
            {
                var config = GetMetaDataConfiguration(metadataType);

                if (string.IsNullOrWhiteSpace(config.MetaDataManagerType) || metadataType != "Project")
                {
                    return null;
                    //throw new FasException(MetaDataExceptionCode.GetMetaDataInfoException,
                    //    string.Format(MetaDataExceptionCode.GetMetaDataInfoExceptionMessage, metadataType + ": MetaDataManagerType为空"));
                }

                return CreateInstance<IMetaDataManager>(config.MetaDataManagerType);
            }
            catch (Exception e)
            {
                throw new FasException(MetaDataExceptionCode.GetMetaDataMgrException,
                    string.Format(MetaDataExceptionCode.GetMetaDataMgrExceptionMessage, metadataType), e);
            }
        }
        public static IMetaDataManager CreateRTPMetaDataManager(string metadataType)
        {
            try
            {
                var config = GetMetaDataConfiguration(metadataType);

                if (string.IsNullOrWhiteSpace(config.MetaDataManagerType))
                {
                    return null;
                    //throw new FasException(MetaDataExceptionCode.GetMetaDataInfoException,
                    //    string.Format(MetaDataExceptionCode.GetMetaDataInfoExceptionMessage, metadataType + ": MetaDataManagerType为空"));
                }

                return CreateInstance<IMetaDataManager>(config.MetaDataManagerType);
            }
            catch (Exception e)
            {
                throw new FasException(MetaDataExceptionCode.GetMetaDataMgrException,
                    string.Format(MetaDataExceptionCode.GetMetaDataMgrExceptionMessage, metadataType), e);
            }
        }

        public static IMetaDataReleaseManager CreateMetaDataReleaseManager(string metadataType)
        {
            try
            {
                var config = GetMetaDataConfiguration(metadataType);

                if (string.IsNullOrWhiteSpace(config.MetaDataReleaseManager))
                {
                    throw new FasException(MetaDataExceptionCode.GetMetaDataInfoException,
                        string.Format(MetaDataExceptionCode.GetMetaDataInfoExceptionMessage, metadataType + ": MetaDataReleaseManager为空"));
                }

                return CreateInstance<IMetaDataReleaseManager>(config.MetaDataReleaseManager);
            }
            catch (Exception e)
            {
                throw new FasException(MetaDataExceptionCode.GetMetaDataMgrException,
                    string.Format(MetaDataExceptionCode.GetMetaDataMgrExceptionMessage, metadataType), e);
            }
        }

        public static IMetaDataSerializer CreateMetadataSerializer(string metadataType)
        {
            try
            {
                var config = GetMetaDataConfiguration(metadataType);

                if (string.IsNullOrWhiteSpace(config.MetadataSerializer))
                {
                    throw new FasException(MetaDataExceptionCode.GetMetaDataInfoException,
                        string.Format(MetaDataExceptionCode.GetMetaDataInfoExceptionMessage, metadataType + ": MetadataSerializer为空"));
                }

                return CreateInstance<IMetaDataSerializer>(config.MetadataSerializer);
            }
            catch (Exception e)
            {
                throw new FasException(MetaDataExceptionCode.GetMetaDataMgrException,
                    string.Format(MetaDataExceptionCode.GetMetaDataMgrExceptionMessage, metadataType), e);
            }
        }

        public static IMetaDataExtPropertyHandler CreateMetaDataExtPropertyHandler(string metadataType)
        {
            try
            {
                var config = GetMetaDataConfiguration(metadataType, false);

                if (config == null) return null;
                //throw new TException("FAS-Meta-0001", "元数据" + metadataType + "的配置为空.");

                if (string.IsNullOrWhiteSpace(config.MetaDataExtPropertyHandler)) return null;
                //throw new TException("FAS-Meta-0001", "元数据" + metadataType + "配置的MetaDataExtPropertyHandler为空.");

                return CreateInstance<IMetaDataExtPropertyHandler>(config.MetaDataExtPropertyHandler);
            }
            catch (Exception e)
            {
                throw new FasException(MetaDataExceptionCode.GetMetaDataMgrException,
                    string.Format(MetaDataExceptionCode.GetMetaDataMgrExceptionMessage, metadataType), e);
            }
        }
        public static IMetaDataContentHandler CreateMetaDataContentHandler(string metadataType)
        {
            try
            {
                var config = GetMetaDataConfiguration(metadataType, false);

                if (config == null) return null;

                if (string.IsNullOrWhiteSpace(config.MetaDataContentType)) return null;

                return CreateInstance<IMetaDataContentHandler>(config.MetaDataContentType);
            }
            catch (Exception e)
            {
                throw new FasException(MetaDataExceptionCode.GetMetaDataMgrException,
                    string.Format(MetaDataExceptionCode.GetMetaDataMgrExceptionMessage, metadataType), e);
            }
        }
        public static IMetaDependencyHandler CreateMetaDependencyHandler(string metadataType)
        {
            try
            {
                var config = GetMetaDataConfiguration(metadataType, false);

                if (config == null) return null;

                if (string.IsNullOrWhiteSpace(config.MetaDataManagerType)) return null;

                return CreateInstance<IMetaDependencyHandler>(config.MetaDataManagerType);
            }
            catch (Exception e)
            {
                throw new FasException(MetaDataExceptionCode.GetMetaDataMgrException,
                    string.Format(MetaDataExceptionCode.GetMetaDataMgrExceptionMessage, metadataType), e);
            }
        }

        public static IMetaDataTermHandler CreateMetaTermHandler(string metadataType)
        {
            try
            {
                var config = GetMetaDataConfiguration(metadataType, false);

                if (config == null) return null;

                if (string.IsNullOrWhiteSpace(config.MetaDataManagerType)) return null;

                return CreateInstance<IMetaDataTermHandler>(config.MetaDataManagerType);
            }
            catch (Exception e)
            {
                throw new FasException(MetaDataExceptionCode.GetMetaDataMgrException,
                    string.Format(MetaDataExceptionCode.GetMetaDataMgrExceptionMessage, metadataType), e);
            }
        }

        public static IMetaDataGenerateHandler CreateMetaDataGenerateService(string metadataType)
        {
            try
            {
                var config = GetMetaDataConfiguration(metadataType);

                if (string.IsNullOrWhiteSpace(config.MetaDataGenerateCode))
                {
                    throw new FasException(MetaDataExceptionCode.GetMetaDataInfoException,
                        string.Format(MetaDataExceptionCode.GetMetaDataInfoExceptionMessage, metadataType + ": MetaDataGenerateCode为空"));
                }

                return CreateInstance<IMetaDataGenerateHandler>(config.MetaDataGenerateCode);
            }
            catch (Exception e)
            {
                throw new FasException(MetaDataExceptionCode.GetMetaDataMgrException,
                    string.Format(MetaDataExceptionCode.GetMetaDataMgrExceptionMessage, metadataType), e);
            }
        }

        private static T CreateInstance<T>(string fullQulifiedTypeName)
        {
            object instance = null;
            try
            {
                Type type = Type.GetType(fullQulifiedTypeName);
                if (type != null)
                {
                    instance = Activator.CreateInstance(type);
                }
                else
                {
                    string[] typeNameArr = fullQulifiedTypeName.Split(',');
                    var dllName = typeNameArr[1] + ".dll";
                    var assembly = Assembly.LoadFrom(dllName);
                    if (assembly != null)
                    {
                        var type1 = assembly.GetType(typeNameArr[0]);
                        if (type1 != null)
                        {
                            instance = Activator.CreateInstance(type1);
                        }
                    }
                }
                if (instance == null)
                {
                    throw new FasException(MetaDataExceptionCode.ReflectMetaDataMgrException,
                        string.Format(MetaDataExceptionCode.ReflectMetaDataMgrExceptionMessage, fullQulifiedTypeName));
                }
            }
            catch (Exception ex)
            {
                throw new FasException(MetaDataExceptionCode.ReflectMetaDataMgrException,
                     string.Format(MetaDataExceptionCode.ReflectMetaDataMgrExceptionMessage, fullQulifiedTypeName), ex);
            }
            return (T)instance;
        }

        private static MetaDataTypeInfo GetMetaDataConfiguration(string metadataType, bool ifNullThrowException = true)
        {
            if (string.IsNullOrWhiteSpace(metadataType))
            {
                throw new FasException(MetaDataExceptionCode.InvalidParameter, MetaDataExceptionCode.InvalidParameterMessage,
                    new ArgumentNullException("MetaDataFactory.GetMetaDataConfiguration.metadataType"));
            }

            var info = new MetaDataTypeInfoDao().GetObject(metadataType);
            if (info == null && ifNullThrowException)
            {
                throw new FasException(MetaDataExceptionCode.GetMetaDataInfoException,
                    string.Format(MetaDataExceptionCode.GetMetaDataInfoExceptionMessage, metadataType));
            }

            return info;
        }

        
    }
}
